home *** CD-ROM | disk | FTP | other *** search
Wrap
unit web; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Sockets; type PClientRec = ^ClientRec; ClientRec = record Socket: integer; BufLen: integer; szBuff: PChar; end; TWebform = class(TForm) Sockets1: TSockets; Memo1: TMemo; procedure Sockets1SessionAvailable(Sender: TObject; Socket: Integer); procedure Sockets1SessionClosed(Sender: TObject; Socket: Integer); procedure Sockets1DataAvailable(Sender: TObject; Socket: Integer); procedure FormCreate(Sender: TObject); procedure Sockets1ErrorOccurred(Sender: TObject; Socket: integer; Error: Integer; Msg: string); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } m_Clients: TList; procedure DropClient(Socket: integer); procedure ProcessReq(Socket: integer); function FindClient(Socket: integer): integer; function GetClient(Socket: integer): PClientRec; procedure SendCannedMsg(Socket: integer; msg: string); procedure Command(Socket: integer; cmd: string); procedure Log(clnt: PClientRec; Status: integer); public { Public declarations } end; TMIMETable = record ext: string; MIMEType: string; end; const message400 = '<HEAD><TITLE>400 Badly Formed Request</TITLE></HEAD>'#13#10'<BODY><H1>400 Badly Formed Request</H1>'#13#10'The request had bad syntax or was inherently impossible to be satisfied.<BR>'#13#10'</BODY>'#13#10#13#10; message404 = '<HEAD><TITLE>404 Not Found</TITLE></HEAD>'#13#10'<BODY><H1>404 Not Found</H1>'#13#10'The requested URL <%s> was not found on this server.<BR>'#13#10'</BODY>'#13#10#13#10; message405 = '<HEAD><TITLE>405 Unknown Method</TITLE></HEAD>'#13#10'<BODY><H1>405 Unknown Method</H1>'#13#10'The requested method <%s> is not supported on this server.<BR>'#13#10'</BODY>'#13#10#13#10; MaxBufferSize = 8192; WWWPort = '80'; HomePath = '.'; DefaultHTML = 'index.html'; MIMETable: array[0..4] of TMIMETable = ( (ext: 'gif'; MIMEType: 'image/gif'), (ext: 'jpg'; MIMEType: 'image/jpg'), (ext: 'htm'; MIMEType: 'text/html'), (ext: 'html'; MIMEType: 'text/html'), (ext: 'txt'; MIMEType: 'text/plain')); var Webform: TWebform; implementation {$R *.DFM} procedure TWebform.Sockets1SessionAvailable(Sender: TObject; Socket: Integer); var clnt: PClientRec; begin GetMem(clnt,sizeof(ClientRec)); clnt^.Socket := Sockets1.SAccept; clnt^.szBuff := StrAlloc(MaxBufferSize); clnt^.BufLen := 0; m_Clients.Add(clnt); end; procedure TWebform.Sockets1SessionClosed(Sender: TObject; Socket: Integer); var i: integer; begin DropClient(Socket); end; procedure TWebform.Sockets1DataAvailable(Sender: TObject; Socket: Integer); var PBuf: PChar; len: integer; pos: integer; clnt: PClientRec; begin clnt := GetClient(Socket); if clnt = nil then begin Memo1.Lines.Add('nil returned from GetClient'); exit; end; len := MaxBufferSize-clnt^.BufLen; pBuf := clnt^.szBuff + clnt^.BufLen; clnt^.BufLen := clnt^.BufLen + Sockets1.SReceive(Socket,PBuf,len); clnt^.szBuff[clnt^.BufLen] := #0; if StrPos(clnt^.szBuff,#13#10#13#10) <> nil then ProcessReq(Socket); end; procedure TWebform.FormCreate(Sender: TObject); begin m_Clients := TList.Create; Sockets1.Port := WWWPort; Sockets1.SListen; Webform.Caption := 'WWW Server - '+Sockets1.HostName; end; procedure TWebform.Sockets1ErrorOccurred(Sender: TObject; Socket: integer; Error: Integer; Msg: string); begin DropClient(Socket); Memo1.Lines.Add(IntToStr(Error)+': '+Msg); end; procedure TWebform.DropClient(Socket: integer); var clnt: PClientRec; begin clnt := GetClient(Socket); if clnt = nil then begin Memo1.Lines.Add('nil client returned from GetClient'); exit; end; m_Clients.Delete(FindClient(Socket)); StrDispose(clnt^.szBuff); FreeMem(clnt); end; function TWebform.FindClient(Socket: integer): integer; begin for result:=0 to m_Clients.Count-1 do begin if Socket = PClientRec(m_Clients.Items[result])^.Socket then break; end; end; function TWebform.GetClient(Socket: integer): PClientRec; var pos: integer; begin Result := nil; for pos:=0 to m_Clients.Count-1 do begin if Socket = PClientRec(m_Clients.Items[pos])^.Socket then begin result := PClientRec(m_Clients.Items[pos]); break; end; end; end; procedure TWebform.ProcessReq(Socket: integer); var clnt: PClientRec; pPath: PChar; pEOS: PChar; ext: string; ContentType: string; f: integer; pBuff: PChar; i: integer; begin clnt := GetClient(Socket); if clnt = nil then begin Memo1.Lines.Add('nil client returned from GetClient'); exit; end; if StrLIComp(clnt^.szBuff,'GET',3) <> 0 then begin SendCannedMsg(Socket,message405); Log(clnt,405); Sockets1.SocketNumber := Socket; Sockets1.SClose; exit; end; pPath := @clnt^.szBuff[4]; pEOS := StrPos(pPath,' '); if pEOS = nil then pEOS := StrPos(pPath,#13); pEOS^ := #0; if StrComp(pPath,'/') = 0 then StrCat(pPath,DefaultHTML); pEOS := StrPos(pPath,'.'); if pEOS = nil then ext := 'txt' else ext := StrPas(pEOS+1); for i:= LOW(MIMETable) to HIGH(MIMETable) do begin if MIMETable[i].ext = ext then begin ContentType := MIMETable[i].MIMEType; break; end; end; Command(Socket,'HTTP/1.0 200 OK'#13#10); Command(Socket,'Server: SockVCL'#13#10); Command(Socket,'MIME-version: 1.0'#13#10); Command(Socket,'Content-type: '+ContentType+#13#10); if not FileExists(HomePath+StrPas(pPath)) then begin SendCannedMsg(Socket,message404); Log(clnt,404); Sockets1.SocketNumber := Socket; Sockets1.SClose; exit; end; f := FileOpen(HomePath+StrPas(pPath),fmOpenRead); clnt^.BufLen := FileSeek(f,0,2); Command(Socket,'Content-length: '+IntToStr(clnt^.BufLen)+#13#10#13#10); FileSeek(f,0,0); pBuff := StrAlloc(clnt^.BufLen); if pBuff = nil then Memo1.Lines.Add('Could not allocate '+IntToStr(clnt^.BufLen)+' bytes of storage') else begin FileRead(f,pBuff^,clnt^.BufLen); FileClose(f); Sockets1.SSend(Socket,pBuff,clnt^.BufLen); log(clnt,200); StrDispose(pBuff); Sockets1.SocketNumber := Socket; Sockets1.SClose; end; end; procedure TWebform.SendCannedMsg(Socket: integer; msg: string); begin Sockets1.SocketNumber := Socket; Sockets1.Text := msg; end; procedure TWebform.FormClose(Sender: TObject; var Action: TCloseAction); begin Sockets1.SCancelListen; end; procedure TWebform.Command(Socket: integer; cmd: string); var sendlen: integer; szBuff: PChar; begin sendlen := Length(cmd); szBuff := StrAlloc(sendlen+1); StrPCopy(szBuff,cmd); Sockets1.SSend(Socket,szBuff,sendlen); StrDispose(szBuff); end; procedure TWebform.Log(clnt: PClientRec; status: integer); begin Memo1.Lines.Add(Sockets1.GetPeerIPAddr(clnt^.Socket)+' - - ['+FormatDateTime('d mmm yyyy hh:mm:ss',now)+'] "'+StrPas(clnt^.szBuff)+'" '+IntToStr(Status)+' '+IntToStr(clnt^.BufLen)); end; end.